home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 4_0 / UUPC3 / (UUPC__) / DCPSYS.C < prev    next >
Text File  |  1992-02-10  |  39KB  |  1,651 lines

  1.  
  2.  
  3. /*            dcpsys.c
  4.  
  5.             Revised edition of dcp
  6.  
  7.             Stuart Lynne May/87
  8.  
  9.             Copyright (c) Richard H. Lamb 1985, 1986, 1987
  10.             Changes Copyright (c) Stuart Lynne 1987
  11.             Portions Copyright ⌐ David Platt, 1992, 1991.  All Rights Reserved
  12.             Worldwide.
  13.  
  14. */
  15. /* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
  16. /* Get the next system, and other support routines  */
  17. #include "dcp.h"
  18. #include <string.h>
  19. /*#define PROTOS  "trkg"*/
  20. #define PROTOS  "gf"
  21. #define MAXLOGTRY       3
  22.  
  23. Proto Protolst[] = {
  24.         'g', ggetpkt, gsendpkt, gopenpk, gclosepk, gfilepkt, geofpkt, grdmsg,  gwrmsg, gsendresp,
  25.         'f', fgetpkt, fsendpkt, fopenpk, fclosepk, ffilepkt, feofpkt, frdmsg,  fwrmsg, fsendresp,
  26. /*
  27.         'k', kgetpkt, ksendpkt, kopenpk, kclosepk,
  28.         'r', rgetpkt, rsendpkt, ropenpk, rclosepk,
  29.         't', tgetpkt, tsendpkt, topenpk, tclosepk,
  30. */
  31.          '0'};
  32.  
  33. #define EOTMSG "\004\r\004\r"
  34.  
  35. procref         getpkt, sendpkt, openpk, closepk, filepkt, eofpkt, getmsg, sendmsg, sendresp;
  36.  
  37. #ifdef THINK_C
  38. int checkcron(void);
  39. #endif
  40.  
  41. void zzz(int nsecs)
  42. {
  43. #ifdef MULTIFINDER
  44.     long int endTime = TickCount() + nsecs * 60L;
  45.     while (TickCount() < endTime) {
  46.       if (Check_Events(10)) 
  47.         if (Main_State == Abort_Program) {
  48.             SIOClose(TRUE);
  49.             exit(-1);
  50.         }
  51.       }
  52. #else
  53.     sleep(nsecs);
  54. #endif
  55. }
  56.  
  57.  
  58. /**/
  59.  
  60. /***************************************************************/
  61. /***            Sub Systems             */
  62. /*
  63. **
  64. **getsystem
  65. ** Process an "systems" file entry (like L.sys)
  66. */
  67. getsystem(rmthost)
  68. char    *rmthost;
  69. {
  70.     int    i,blankline;
  71.     char tmpline[BUFSIZ],*p;
  72.     
  73.     *sysline = 0;    /* empty out sysline */
  74.     while(fgets( tmpline, BUFSIZ, fsys) != (char *)NULL) {
  75.         for(blankline=TRUE, p=tmpline; *p; p++) {
  76.             if(!isspace(*p)) {
  77.                 blankline = FALSE;
  78.                 break;
  79.             }
  80.         }
  81.         if(blankline)            /* skip blank lines */
  82.             continue;
  83.         if(*p == '#')            /* skip comment lines */
  84.             continue;
  85.         
  86.         if(tmpline[strlen(tmpline)-2] == '\\') {
  87.             tmpline[strlen(tmpline)-2] = ' ';    /* got continuation line */
  88.             tmpline[strlen(tmpline)-1] = (char)NULL;    /* throw away the newline char */
  89.             strcat(sysline, tmpline);
  90.             continue;
  91.         }
  92.         else {
  93.             strcat(sysline, tmpline);        /* not continued, take it and move on */
  94.             break;
  95.         }
  96.     }
  97.     
  98.     if(strlen(sysline) == 0)
  99.         return('A');
  100.  
  101.     printmsg( 2, "%s", sysline );
  102.  
  103.     kflds = getargs( sysline, flds );
  104.     
  105.     /* if this system isn't the one we're calling or we're not calling
  106.        a special set of systems then return 'I' and try the next one */
  107.     if ( strcmp(rmthost, flds[FLD_REMOTE] ) != SAME &&
  108.          strcmp(rmthost, "list") != SAME &&
  109.          strcmp(rmthost, "any")  != SAME &&
  110.          strcmp(rmthost, "all")  != SAME &&
  111.          strcmp(rmthost, "cron") != SAME &&
  112.          strcmp(rmthost, "need") != SAME &&
  113.          strcmp(rmthost, "auto") != SAME)
  114.         return( 'I' );
  115.     
  116.     if (strcmp(rmthost, "INCOMING") == SAME && remote == MASTER) {
  117.         return ('I');
  118.     }
  119.         
  120.     strcpy( rmtname, flds[FLD_REMOTE] );
  121.     cctime = flds[FLD_CCTIME];
  122.     strcpy( device, flds[FLD_DEVICE] );
  123.  
  124.     /* strcpy( type, flds[FLD_TYPE] ); */
  125.     strcpy( speed, flds[FLD_SPEED] );
  126.     strcpy( proto, flds[FLD_PROTO] );
  127.     strcpy( phone, flds[FLD_PHONE] );
  128.  
  129.     if (debuglevel > 3)
  130.         for (i = FLD_EXPECT; i < kflds; i += 2)
  131.             fprintf( stderr, "expect[%02d]:\t%s\nsend  [%02d]:\t%s\n",
  132.                 i, flds[i], i+1, flds[i+1] );
  133.  
  134.     printmsg( 2, "rmt= %s ctm= %s", rmtname, flds[FLD_CCTIME] );
  135.     printmsg( 2, "dev= %s ", device );
  136.     printmsg( 2, "spd= %s pro= %s", speed, proto );
  137.     printmsg( 2, "phn= %s ", phone );
  138.     
  139.     if (fw != (FILE *)NULL) {
  140.         fclose(fw);
  141.         fw = (FILE *)NULL;
  142.     }
  143.     
  144.     if (strcmp(rmthost, "list") == SAME) {
  145.         return 'I';
  146.     }
  147.     
  148.     /* first make sure it's ok to call the system at this time, if so,
  149.        then make sure it's a system we are supposed to call */
  150.     strcpy(callcause, "user request");
  151.     if ( ((strcmp(rmthost, "all")   == SAME && strcmp(rmtname, "INCOMING") != SAME) ||
  152.           (strcmp(rmthost, rmtname) == SAME) ||
  153.            ((strcmp(rmthost, "any") == SAME) && scandir() == 'S') ||
  154.            ((strcmp(rmthost, "cron") == SAME) && checkcron() == 'S') ||
  155.            ((strcmp(rmthost, "need") == SAME || strcmp(rmthost, "auto") == SAME) && (scandir() == 'S' || checkcron() == 'S')))
  156.        )
  157.     {
  158.         if (fw != (FILE *)NULL) {
  159.             fclose(fw);
  160.             fw = (FILE *)NULL;
  161.         }
  162.         if ( checktime(cctime) ) {
  163.             return('S');      /* startup this system */
  164.         } else {
  165.             return('T');      /* wrong time */
  166.         }
  167.     } else {
  168.         if (fw != (FILE *)NULL) {
  169.             fclose(fw);
  170.             fw = (FILE *)NULL;
  171.         }
  172.         return('I');    /* don't call this system, try the next one */
  173.     }
  174. }
  175.  
  176.  
  177. /**/
  178. /*
  179. **
  180. **checkname
  181. ** Do we know the guy ?
  182. */
  183. checkname(name)
  184. char    name[];
  185. {
  186.     FILE *ff;
  187.     char line[BUFSIZ], tmp[20]; /* can change to 8 if %8s works */
  188.  
  189.     if ( ( ff = FOPEN( s_systems, "r", 't' )) == (FILE *)NULL )
  190.         return( FAILED );
  191.  
  192.     while ( fgets( line, BUFSIZ, ff ) != (char *)NULL ){
  193.         sscanf( line, "%8s ", tmp );
  194.         printmsg( 3, "rmt= %s sys= %s", name, tmp );
  195.         if (strncmp(line, "ANONYMOUS", 9) == 0 || strncmp( tmp, name, 7 ) == 0 ) {
  196.             fclose( ff );
  197.             return ( OK ); /*OK I like you */
  198.         }
  199.     }
  200.     fclose( ff );
  201.     return( FAILED ); /* Who are you ? */
  202.  
  203. }
  204.  
  205.  
  206. typedef struct {
  207.     char min[40];
  208.     char hour[40];
  209.     char day[40];
  210.     char month[40];
  211.     char weekday[40];
  212.     char name[40];
  213.     int retrytime;    /* minutes between retries */
  214. } schedule_record;
  215.     
  216. typedef int datalist[61];
  217.  
  218. typedef struct {
  219.     datalist min;
  220.     datalist hour;
  221.     datalist day;
  222.     datalist month;
  223.     datalist weekday;
  224. } schedule_list_record;
  225.  
  226. void Schedule_To_List(char *Schedule, datalist Schedule_List, int Min, int Max);
  227. void Compute_Next_Call_Time(status_record Last, schedule_record Schedule, struct tm *Next );
  228. int Time_Less_Than_Or_Equal(struct tm *Left, struct tm *Right);
  229.  
  230. int Time_Less_Than_Or_Equal(Left, Right)
  231. struct tm *Left;
  232. struct tm *Right;
  233. {
  234.     /* check the months first */
  235.     if (Left->tm_mon < Right->tm_mon) return TRUE;
  236.     if (Left->tm_mon > Right->tm_mon) return FALSE;
  237.     
  238.     /* months are the same, check the day */
  239.     if (Left->tm_mday < Right->tm_mday) return TRUE;
  240.     if (Left->tm_mday > Right->tm_mday) return FALSE;
  241.     
  242.     /* days are the same, check the hour */
  243.     if (Left->tm_hour < Right->tm_hour) return TRUE;
  244.     if (Left->tm_hour > Right->tm_hour) return FALSE;
  245.     
  246.     /* hours are the same, check the minute */
  247.     if (Left->tm_min > Right->tm_min) return FALSE;
  248.     return TRUE;
  249. }
  250.  
  251.  
  252. void Schedule_To_List(Schedule, Schedule_List, Min, Max)
  253. char *Schedule;
  254. datalist Schedule_List;
  255. int Min, Max;
  256. {
  257.     /* take a character string describing this schedule entry and
  258.        convert it to a list of times that are acceptable, see format
  259.        and examples below.
  260.        
  261.        Format (no spaces allowed in actual string):
  262.            number :== digit{digit}
  263.            range  :== number '-' number
  264.            item   :== range | number    
  265.            entry  :==  '*' | item {, item}
  266.        Example:
  267.            "*"  "1-5,8"  "1,3,5,7,9,11" "0-7,17-23"
  268.     */
  269.     int i,k,m;
  270.     char *p;
  271.     
  272.     if (strcmp(Schedule,"*")==SAME) {
  273.         for (i=0, k=Min; k<=Max; k++, i++) 
  274.             Schedule_List[i] = k;
  275.         return; 
  276.     }
  277.     
  278.     /* scan for list entries */
  279.     p = Schedule;
  280.     i = 0;
  281.     while (*p) {
  282.         if (isdigit(*p)) {
  283.             /* got a number */
  284.             sscanf(p, "%d", &k);        /* got a list entry */
  285.             Schedule_List[i++] = k;        /* put it in the list */
  286.             while (isdigit(*p)) p++;    /* skip past number */
  287.             
  288.         } else if (*p == ',') {
  289.             /* got a comma */
  290.             p++;        /* skip the comma */
  291.         } else if (*p == '-') {
  292.             /* got a dash, must be a range */
  293.             p++;        /* skip the dash */
  294.             sscanf(p, "%d", &m);        /* get the end of the range */
  295.             while (k <= m) {            /* put entries for the range in the list */
  296.                 Schedule_List[i++] = k++;
  297.             }
  298.             while (isdigit(*p)) p++;    /* skip past number */
  299.         } else {
  300.             p++;
  301.         }
  302.         Schedule_List[i] = -1;
  303.     }
  304. }    
  305.  
  306. int Validate_Value(int Value, datalist Valid_List);
  307. int Validate_Value(Value, Valid_List)
  308. int Value;
  309. datalist Valid_List;
  310. {
  311.     int i = 0;
  312.  
  313.     while ((Valid_List[i] < Value) && (Valid_List[i] >= 0))
  314.         i++;
  315.     
  316.     if (Valid_List[i] < 0) {
  317.         /* didn't find the value, use the first entry */
  318.         return Valid_List[0];
  319.     } else {
  320.         /* found the value or the next larger one, it's ok to use it */
  321.         return Valid_List[i];
  322.     }
  323. }
  324.  
  325. int Add_Field(int Last, int *Next, datalist Valid_List, int *Carry);
  326. int Add_Field(Last, Next, Valid_List, Carry)
  327. int  Last;
  328. int *Next;
  329. datalist Valid_List;
  330. int *Carry;
  331. {
  332.     *Next = Last + *Carry;        /* add the carry in (may be 0) */
  333.     
  334.     /* make sure the time is a valid value for this field */
  335.     *Next = Validate_Value(*Next, Valid_List);
  336.     
  337.     /* if the value is lower than the last time, set the carry flag (overflow) */
  338.     if (*Next < Last) {
  339.         *Carry = 1;        /* to make it less we had to wrap around, causing a carry */
  340.     } else if (*Next == Last && *Carry == 1) {
  341.         /* we had a carry but it didn't increment; it must have wrapped all the
  342.            way back around to where we started, this should cause a carry */
  343.         *Carry = 1;
  344.     } else {
  345.         *Carry = 0;
  346.     }
  347.         
  348.     /* if the value is different from last time, then return 1 to indicate it
  349.        must reset the less significant fields to their minimum values */
  350.     if (*Next != Last || *Carry == 1) return 1;
  351.     return 0;
  352. }
  353.  
  354. int Day_Of_Week(int Month, int Day, int Year);
  355. int Day_Of_Week(Month, Day, Year)
  356. int Month;        /* 1-12 */
  357. int Day;        /* 1-31 */
  358. int Year;        /* 1904-2040 */
  359. /* Returns Day_Of_Week where 1=Mon...5=Fri, 6=Sat, 7=Sun */
  360. {
  361.     DateTimeRec Tmp_DTR;
  362.     long Secs;
  363.     
  364.     Tmp_DTR.year   = (Year >= 80 ? 1900+Year : 2000+Year);
  365.     Tmp_DTR.month  = Month;
  366.     Tmp_DTR.day    = Day;
  367.     Tmp_DTR.hour   = 0;
  368.     Tmp_DTR.minute = 0;
  369.     Tmp_DTR.second = 0;
  370.     Tmp_DTR.dayOfWeek = 1;
  371.     
  372.     Date2Secs(&Tmp_DTR, &Secs);    /* day of week not needed */
  373.     Secs2Date(Secs, &Tmp_DTR);    /* day of week return in conversion */
  374.     
  375.     if (Tmp_DTR.dayOfWeek == 1) 
  376.         return 7;  /* Sunday */
  377.     else
  378.         return Tmp_DTR.dayOfWeek - 1;
  379. }
  380.  
  381. void Compute_Next_Call_Time(Last, Schedule, Next)
  382. status_record Last;
  383. schedule_record Schedule;
  384. struct tm *Next;
  385. {
  386.     schedule_list_record Valid_Lists;    
  387.     int carry;                /* start with a carry to increment to next time value */
  388.     int field = 0;
  389.     struct tm Last_Time;
  390.     
  391.     Last_Time = *localtime(&Last.time_secs);
  392.     Last_Time.tm_mon++;        /* make months 1 based */
  393.     *Next = Last_Time;
  394.     
  395.     Schedule_To_List(Schedule.min,     Valid_Lists.min,     0, 59);
  396.     Schedule_To_List(Schedule.hour,    Valid_Lists.hour,    0, 23);
  397.     Schedule_To_List(Schedule.day,     Valid_Lists.day,     1, 31);
  398.     Schedule_To_List(Schedule.month,   Valid_Lists.month,   1, 12);
  399.     Schedule_To_List(Schedule.weekday, Valid_Lists.weekday, 1, 7);
  400.  
  401.     /* find the next larger valid time for the field */
  402.     carry = 1;
  403.     if (Add_Field(Last_Time.tm_min, &Next->tm_min, Valid_Lists.min, &carry)) {
  404.         /* field was set backwards, we must update the less significant fields
  405.             to their minimum values */
  406.         /* there are no less significant fields (we don't use seconds at all) */
  407.     }
  408.  
  409.     if (Add_Field(Last_Time.tm_hour, &Next->tm_hour, Valid_Lists.hour, &carry)) {
  410.         /* field was set backwards, we must update the less significant fields to their
  411.            minimum values */
  412.         Next->tm_min = Valid_Lists.min[0];
  413.     }
  414.  
  415.   try_the_next_day:
  416.       
  417.     if (Add_Field(Last_Time.tm_mday, &Next->tm_mday, Valid_Lists.day, &carry)) {
  418.         /* field was set backwards, we must update the less significant fields to their
  419.            minimum values */
  420.         Next->tm_hour = Valid_Lists.hour[0];
  421.         Next->tm_min  = Valid_Lists.min[0];
  422.     }
  423.     
  424.     if (Add_Field(Last_Time.tm_mon, &Next->tm_mon, Valid_Lists.month, &carry)) {
  425.         /* field was set backwards, we must update the less significant fields to their
  426.            minimum values */
  427.         Next->tm_mday = Valid_Lists.day[0];
  428.         Next->tm_hour = Valid_Lists.hour[0];
  429.         Next->tm_min  = Valid_Lists.min[0];
  430.     }
  431.     
  432.     /* see if day of week of the computed next call time is a valid 
  433.        day of the week given the days that are allowed */
  434.     Next->tm_wday = Day_Of_Week(Next->tm_mon, Next->tm_mday, Next->tm_year);
  435.     if (Validate_Value(Next->tm_wday, Valid_Lists.weekday) != Next->tm_wday) {
  436.       /* weekday doesn't match list of valid weekdays, so try the next 
  437.          possible day that we could call and see if it falls on the right
  438.          weekday.  Keep doing this until we find a valid day that is on a valid
  439.          weekday. */
  440.       Last_Time = *Next;
  441.       carry = 1;        /* so day will get incremented */
  442.       goto try_the_next_day;
  443.     }
  444.     
  445.     Next->tm_mon--;        /* make months 0 based again */
  446.     
  447.     /*** weekday restrictions are not being handled yet ***/
  448. }
  449.  
  450. /* get status information from file.  Returns TRUE on success, FALSE on failure. */
  451.  
  452. int GetStatus()
  453. {
  454.     FILE *fp;
  455.     char line[BUFSIZ];
  456.     char stfile[80];            /* constructed status file name */
  457.     int n;
  458.     if (strcmp(Last.name, rmtname) == SAME) {
  459.         return TRUE;
  460.     }
  461.     sprintf(stfile, "%s%s", s_statfile, rmtname);
  462.     
  463.     /* if there is no status file, assume it has never been called */
  464.     if ((fp=FOPEN(stfile, "r", 't')) == (FILE *)NULL) {
  465.         printmsg( 1, "No status file for system %s", rmtname );
  466.         goto fakeit;
  467.     }
  468.     
  469.     n = 0;
  470.     if (fgets(line, BUFSIZ, fp) != (char *)NULL) {
  471.         /* got status line into buffer */
  472.         /* line format:
  473.                 ctime system status [failures]
  474.            ctime is epoch time in seconds from time function
  475.            status may be OK or FAILED */
  476.         Last.failures = 0;
  477.         n = sscanf(line, "%ld %s %s %d",
  478.                    &Last.time_secs, Last.name, Last.status, &Last.failures);
  479.         if (n < 3 ||
  480.             strcmp(rmtname, Last.name) != SAME) n = 0;
  481.     }
  482.     fclose(fp);
  483.     if (n == 0) {
  484.         printmsg( 1, "Unable to read status line" );
  485. fakeit: strcpy(Last.name, rmtname);
  486.         strcpy(Last.status, "OK");
  487.         Last.failures = 0;
  488.         Last.time_secs = 0;
  489.         return FALSE;
  490.     }
  491.     return TRUE;
  492. }
  493.  
  494. /**/
  495. /*
  496. **
  497. ** checkcron()
  498. ** check if we should call a system at this time.
  499. **
  500. ** returns 'S' if system needs be called
  501. ** returns 'I' if system doesn't need to be called
  502. **
  503. ** "need" is based on schedule file not by what is spooled, use "any"
  504. ** if you want to send spooled data out.
  505. **
  506. ** system needs to be called if any of the following conditions are met:
  507. **
  508. ** (1) status file "ST.<system>" doesn't exist
  509. ** (2) status file indicates last call failed and the elapsed time since
  510. **     the failure exceeds the retrytime entry in the schedule file.
  511. ** (3) status file indicates last call was ok and according to the
  512. **     schedule file there should have been a call during the time when
  513. **     the last called occurred and the current time.
  514. */
  515. int checkcron()
  516. {
  517.     FILE *fp;
  518.     char line[BUFSIZ];
  519.     char stfile[80];            /* constructed status file name */
  520.     int n;
  521.     time_t Cur_Time_Secs, Retry_Expiration;
  522.     
  523.     schedule_record Schedule;
  524.     struct tm Next, Current_Time;
  525.     
  526.     /* got a real problem if schedule file is missing */
  527.     if ((fp=FOPEN(s_schedule, "r", 't')) == (FILE *)NULL) {
  528.         printmsg( 1, "Schedule file '%s' missing", s_schedule );
  529.         return('I');        /* no schedule, so don't call anyone */
  530.     }
  531.     
  532.     n = 0;
  533.     while (n==0 && fgets(line, BUFSIZ, fp) != (char *)NULL){
  534.         /* line format:
  535.             min hour day month weekday system [retrytime] */
  536.         if (line[0] != '#') {
  537.             Schedule.retrytime = 1;
  538.             n = sscanf(line, "%s %s %s %s %s %s %d",
  539.                        Schedule.min, Schedule.hour, Schedule.day,
  540.                        Schedule.month, Schedule.weekday, Schedule.name,
  541.                        &Schedule.retrytime);
  542.             if (n < 6 ||
  543.                 strcmp(rmtname, Schedule.name) != SAME) n = 0;
  544.         }
  545.     }
  546.     fclose(fp);
  547.     if (n == 0) {
  548.         printmsg( 1, "System %s not in schedule", rmtname );
  549.         return ('I');    /* didn't find the system in schedule, don't call it */
  550.     }
  551.     
  552.     /* we have the schedule now, now we need the current status */
  553.     if (!GetStatus()) {
  554.         strcpy(callcause, "scheduled call");
  555.         return('S');
  556.     }
  557.     
  558.     if (strcmp(Last.status,"OK") != SAME  && Schedule.retrytime) {
  559.         /* no retries if retrytime is 0, just the scheduled calls */
  560.         
  561.         /* last call failed, see if failed during current run.  If so,
  562.            try again (additional phone number) */
  563.         if (Last.time_secs >= runStartSecs) {
  564.             return ('S');
  565.         }
  566.         /* Failed during previous run.  See if the retry time has expired */
  567.         Retry_Expiration = Last.time_secs + Schedule.retrytime * 60;
  568.         time(&Cur_Time_Secs);
  569.         if (Cur_Time_Secs >= Retry_Expiration) {
  570.             printmsg( 1, "RETRY time for %s", rmtname );
  571.             strcpy(callcause, "retry of scheduled call");
  572.             return ('S');        /* retry time past, call system again */
  573.         } else {
  574.             printmsg( 1, "Retry time for %s not reached yet", rmtname );
  575.             return ('I');        /* not time yet, don't call system */
  576.         }
  577.     }
  578.     
  579.     /* last call was successful, see if it's time to call this system again */
  580.     Compute_Next_Call_Time( Last,        /* time of last successful call */
  581.                             Schedule,    /* time schedule pattern */
  582.                             &Next);        /* next time it should be called */
  583.                             
  584.     time(&Cur_Time_Secs);
  585.     Current_Time = *localtime(&Cur_Time_Secs);
  586.     
  587.     if (Time_Less_Than_Or_Equal(&Next, &Current_Time) == TRUE) {
  588.         /* the Next time has past (it's less than the current time) so that means
  589.            we should call this system */
  590.         strcpy(callcause, "scheduled call");
  591.         return ('S');        /* call this system */
  592.     } else {
  593.         printmsg( 1, "Scheduled call time for %s not reached yet",
  594.                      rmtname );
  595.         return ('I');        /* not time to call yet, don't call system */
  596.     }
  597. }
  598.  
  599.  
  600. void Update_Status(New_Status)
  601. int New_Status;
  602. {
  603.     /* rewrite status file with latest results */
  604.     char stfile[80];
  605.     time_t cur_time;
  606.     FILE *fp;
  607.     
  608.     sprintf(stfile, "%s%s", s_statfile, rmtname);
  609.     
  610.     if ((fp=FOPEN(stfile, "w", 't')) == (FILE *)NULL) return;
  611.     
  612.     time(&cur_time);
  613.     if (New_Status == OK) {
  614.         fprintf(fp, "%ld %s %s\r",
  615.                 cur_time, rmtname, "OK");
  616.         Last.time_secs = cur_time;
  617.     } else {
  618.         fprintf(fp, "%ld %s %s %d\r",
  619.             cur_time, rmtname, "FAILED", failureCount);
  620.     }
  621.     fclose(fp);
  622. }
  623.  
  624. /**/
  625. /*
  626. **
  627. **checktime
  628. ** check if we may make a call at this time
  629. **
  630. ** acceptable formats:  "Any", "Evening", "Night", "hhmm-hhmm"
  631. ** hhmm-hhmm may be a inclusive range, ie: 0000-0600,
  632. ** or it can be an range that specifies morning and evening hours,
  633. ** ie: 1700-0700 (means 0000-0700 and 1700-2359)
  634. **
  635. ** Evening includes the standard AT&T long distance hours from 1700 to
  636. ** 0800 plus all day Saturday and all day Sunday except evening hours.
  637. **
  638. ** Time may also include a retry interval (e.g. "evening;10") to specify
  639. ** the minimum retry interval.  If a retry interval is specified, it will
  640. ** be used precisely as given.  If no retry interval is specified, a
  641. ** HoneyDanBer-style exponential backoff algorithm is used... the retry
  642. ** time will be 5 minutes after the first failed attempt, 10 minutes after
  643. ** the second, 20 after the third, and so forth... up to a maximum backoff
  644. ** of 23 hours.
  645. **
  646. ** The retry interval is applied during calls to "any", "all", "cron", and
  647. ** "auto".  It is _not_ applied during a call directed to a specific site...
  648. ** this allows the user to force a call without having to manually trash
  649. ** the ST.sitename file.
  650. */
  651. checktime(xtime)
  652. char    xtime[];
  653. {
  654.     struct tm    *t;
  655.     int Cur_Time = 0;
  656.     int Left,Right;
  657.     int Is_OK = FALSE;
  658.     char mytime[256],retrystring[256];
  659.     char line[BUFSIZ];
  660.     long int backoff;
  661.     char *p;
  662.     int i, n;
  663.     char stfile[80];            /* constructed status file name */
  664.     time_t Retry_Expiration;
  665.     FILE *fp;
  666.     
  667.     if ((p = strchr(xtime, ';')) == NULL) {
  668.         strcpy(mytime, xtime);
  669.         backoff = -1;
  670.     } else {
  671.         strncpy(mytime, xtime, p - xtime);
  672.         mytime[p-xtime] = '\0';
  673.         if (sscanf(p+1, "%ld", &backoff) != 1 || backoff <= 0 || backoff > 60*24*7) {
  674.             backoff = -1;
  675.         }
  676.     }
  677.     time(&theTime);
  678.     t = localtime(&theTime);
  679.     Cur_Time = t->tm_hour*100 + t->tm_min;
  680.     
  681.     for (p=mytime; *p; p++) *p = tolower(*p);    /* convert to lower */
  682.     
  683.     printmsg( 2, "curtime= %d mytime= %s", Cur_Time, mytime );
  684.  
  685.     if (strcmp(mytime,"any")==SAME) {
  686.         /* any time allowed */
  687.         Is_OK = TRUE;
  688.         
  689.     } else if (isdigit(*mytime) &&
  690.                (sscanf(mytime,"%d-%d",&Left,&Right) == 2)) {
  691.         /* time range */
  692.         if (Left <= Right) {
  693.             /* inclusive range, ie: 1700-2300 */
  694.             if (Cur_Time >= Left && Cur_Time < Right) Is_OK = TRUE;
  695.         } else {
  696.             /* complex range, ie: 2300-0800 */
  697.             /* ranges are: 0000-Right + Left-2359 */
  698.             if (Cur_Time < Right || Cur_Time >= Left) Is_OK = TRUE;
  699.         }
  700.         
  701.     } else if (strcmp(mytime,"evening")==SAME) {
  702.         /* evening time period (includes night rates, basicall anytime
  703.            except weekday daytime rates) */
  704.         if (Cur_Time <  800  ||        /* early morning is night rate */
  705.             Cur_Time >= 1700 ||        /* evening is evening or night rate */
  706.             t->tm_wday == 0  ||     /* sunday is all evening or night */
  707.             t->tm_wday == 6)         /* saturday is night rates */
  708.           Is_OK = TRUE;
  709.         
  710.     } else if (strcmp(mytime,"night")==SAME) {
  711.         /* night rate time period */
  712.         if (Cur_Time <  800 ||        /* early morning is night rates */
  713.             Cur_Time >= 2300 ||        /* late night rates */
  714.             t->tm_wday == 6  ||     /* saturday is night rates */
  715.                                     /* sunday daytime is night rates, evening
  716.                                        night rates already handled */
  717.             (t->tm_wday == 0 &&    Cur_Time < 1700) ||
  718.                                     /* friday evening is night rates */
  719.             (t->tm_wday == 5 && Cur_Time >= 1700))
  720.           Is_OK = TRUE;
  721.         
  722.     } else if (strcmp(mytime,"never")==SAME) {
  723.         Is_OK = FALSE;
  724.         
  725.     } else {
  726.         /* didn't match known formats, flag an format error */
  727.         printmsg( 0, "bad time format in System file: %s", mytime );
  728.     }
  729.  
  730.     if (debuglevel > 0 && !Is_OK) {
  731.         printmsg( 1, "wrong time to call %s, allowed at: %s",
  732.                      rmtname, mytime);
  733.     }
  734.     if (!Is_OK) {
  735.         return FALSE;
  736.     }
  737.     
  738.     /* it's the right time of day. now we need the current status */
  739.     if (!GetStatus()) {
  740.         failureCount = 0;
  741.         return('S');
  742.     }
  743.     
  744.     failureCount = Last.failures;
  745.     
  746.     if (strcmp(Last.status,"OK") == SAME || strcmp(rmtname, Rmtname) == SAME) {
  747.         return TRUE;
  748.     }
  749.  
  750.     /* Failed during previous run.  See if the retry time has expired */
  751.     if (backoff == -1) { /* HDB-style exponential backoff */
  752.         if (failureCount == 0) {
  753.             backoff = 5;
  754.         } else if (failureCount >= 10) {
  755.             backoff = 23 * 60;
  756.         } else {
  757.             backoff = 5 << (failureCount - 1);
  758.         }
  759.     }
  760.     Retry_Expiration = Last.time_secs + backoff * 60;
  761.     if (theTime >= Retry_Expiration) {
  762.         return (TRUE);        /* retry time past, call system again */
  763.     } else {
  764.         printmsg( 1, "Retry time for %s not reached yet, %ld minutes to go", rmtname,
  765.                     (Retry_Expiration - theTime + 59) / 60 );
  766.         return (FALSE);        /* not time yet, don't call system */
  767.     }
  768. }
  769.  
  770. /**/
  771. /*
  772. **
  773. **      delay
  774. **
  775. */
  776. /*ddelay(dtime)
  777. int    dtime;
  778. {
  779.     int    i, j;
  780.     for (i = 0; i < dtime; i++) {
  781.     }
  782. }
  783.  
  784. */
  785.  
  786. paceit ()
  787. {
  788.     EventRecord    theEvent;
  789.     long timea;
  790.  
  791.     timea = Ticks+4; /* 1/15 - 1/20 second spin */
  792.  
  793.     while (Ticks < timea) {
  794. #ifdef MULTIFINDER
  795.         Check_Events(MF_DELAY);
  796. #else
  797.         (void) EventAvail(everyEvent, &theEvent);
  798.         SystemTask();
  799. #endif
  800.     }
  801. }
  802.  
  803.  
  804. /**/
  805. /*
  806. **
  807. **sysend
  808. ** end UUCP session negotiation
  809. */
  810. sysend()
  811. {
  812.     char    msg[80];
  813.  
  814.     msg[1] = '\0';
  815.     msgtime = 5; /* dplatt, don't hang around for so long... */
  816. /*     msgtime = 2 * MSGTIME; */
  817.     wmsg("OOOOOO", 2);
  818.     if (rmsg(msg, 2) == -1)
  819.             goto hang;
  820.     /*}*/
  821. hang:
  822.     wmsg("OOOOOO", 2);
  823.     
  824.     closeline();
  825.     printmsg( 0, "Over and out");
  826.     if ( remote == MASTER )
  827.         return('I');
  828.     return('A');
  829. }
  830.  
  831.  
  832. /*
  833. **
  834. **wmsg
  835. ** write a ^P type msg to the remote uucp
  836. */
  837. wmsg(msg, syn)
  838. int    syn;
  839. char    msg[];
  840. {
  841.     int    len;
  842.     len = strlen(msg);
  843.     if (syn == 2)
  844.         swrite("\0\020", 2);
  845.     swrite(msg, len);
  846.     if (syn == 2)
  847.         swrite("\0", 1);
  848. }
  849.  
  850.  
  851. /*
  852. **
  853. **rmsg
  854. ** read a ^P msg from UUCP
  855. */
  856. rmsg(msg, syn)
  857. int    syn;
  858. char    msg[];
  859. {
  860.     int    ii;
  861.     char    c, cc[5];
  862.     /* *msg0;*/
  863.     /*msg0 = msg;*/
  864.     
  865.     c = 'a';
  866.     if (syn == 2) {
  867.         while ((c & 0x7f) != '\020') {
  868.             if (sread(cc, 1, msgtime) < 1)
  869.                 return(-1);
  870.             c = cc[0]; /* Dont ask. MSC needs more than a byte to breathe */
  871.             /*        printf("Hello im in rmsg c=%x\n",c); */
  872.         }
  873.     }
  874.     for (ii = 0; ii < 132 && c ; ii++) {
  875.         if (sread(cc, 1, msgtime) < 1)
  876.             return(-1);
  877.         c = cc[0] & 0x7f;
  878.         if (c == '\r' || c == '\n')
  879.             c = '\0';
  880.         msg[ii] = c;
  881.         /*if(c == '\020') msg = msg0; */
  882.     }
  883.  
  884.     return(strlen(msg));
  885. }
  886.  
  887.  
  888.  
  889. /**/
  890. /*
  891. **
  892. **
  893. **startup
  894. **
  895. **
  896. */
  897. startup()
  898. {
  899.     char    msg[255], tmp1[255], tmp2[255];
  900.     memset((void *) &remote_stats, 0, (size_t) sizeof remote_stats);
  901.     if ( remote == MASTER ) {
  902.         msgtime = 2 * MSGTIME;
  903.         if (rmsg(msg, 2) == -1) {
  904.             printmsg( 2, "1st msg never arrived" );
  905.             return('X');
  906.         }
  907.         printmsg( 2, "1st msg = %s", msg );
  908.         if (msg[5] == '=' && strncmp(&msg[6], rmtname, 7)) {
  909.             printmsg( 2, "Not who we expected it to be" );
  910.             return('Y');
  911.         }
  912.  
  913.  
  914.         /*sprintf(msg, "S%.7s -Q0 -x%d", nodename, debuglevel);*/  /* -Q0 -x16 remote debuglevel set */
  915.  
  916.         sprintf(msg, "S%s", shortname);
  917.  
  918.         wmsg(msg, 2);
  919.         if (rmsg(msg, 2) == -1) {
  920.             printmsg( 2, "2nd msg never arrived" );
  921.             return('X');
  922.         }
  923.         printmsg( 2, "2nd msg = %s", msg );
  924.         if (strncmp(&msg[1], "OK", 2)) {
  925.             printmsg( 2, "2nd msg not OK" );
  926.             printmsg( 0, "2nd msg: %s", msg);
  927.             return('Y');
  928.         }
  929.         if (rmsg(msg, 2) == -1) {
  930.             printmsg( 2, "3rd msg never arrived" );
  931.             return('X');
  932.         }
  933.         printmsg( 2, "3rd msg = %s", msg );
  934.         if (msg[0] != 'P' || index(&msg[1], proto[0]) == (char *)NULL) {
  935.             printmsg(0, "Protocol disagreement");
  936.             wmsg("UN", 2);
  937.             return('Y');
  938.         }
  939.         sprintf(msg, "U%c", proto[0]);
  940.         wmsg(msg, 2);
  941.         setproto(proto[0]);
  942.         printmsg( 0, "OK Startup");
  943.         return('D');
  944.     } else {
  945.         msgtime = 2 * MSGTIME;
  946.         sprintf(msg, "Shere=%s", shortname);
  947.         wmsg(msg, 2);
  948.         if (rmsg(msg, 2) == -1)
  949.             return('Y');
  950.         sscanf(&msg[1], "%s %s %s", rmtname, tmp1, tmp2);
  951.         sscanf(tmp2, "-x%d", &debuglevel);
  952.         printmsg( 1, "debuglevel level = %d", debuglevel );
  953.         printmsg( 2, "1st msg from remote = %s", msg );
  954.         if (checkname(rmtname)) {
  955.             wmsg("RYou are unknown to me", 0);
  956.             printmsg(0, "Rejected a connection from %s (unknown)", rmtname);
  957.             zzz(1);
  958.             return('Y');
  959.         }
  960.         wmsg("ROK", 2);
  961.         sprintf(msg, "P%s", PROTOS);
  962.         wmsg(msg, 2);
  963.         if (rmsg(msg, 2) == -1)
  964.             return('Y');
  965.         if (msg[0] != 'U' || index(PROTOS, msg[1]) == (char *)NULL ) {
  966.             printmsg(0, "Protocol disagreement with %s", rmtname);
  967.             return('Y');
  968.         }
  969.         proto[0] = msg[1];
  970.         setproto(proto[0]);
  971.         printmsg( 0, "Call from %s connected", rmtname);
  972.         return('R');
  973.     }
  974. }
  975.  
  976.  
  977. /******* set the protocol **********/
  978. setproto(pr)
  979. char    pr;
  980. {
  981.     int    i;
  982.     Proto * tproto;
  983.     for (tproto = Protolst; tproto->type != '\0' && pr != tproto->type; tproto++) {
  984.         printmsg( 3, "setproto: %c %c", pr, tproto->type );
  985.     }
  986.     if (tproto->type == '\0') {
  987.         printmsg( 0, "setproto:You said I had it but I cant find it" );
  988.         SIOClose(TRUE);
  989.         exit(1);
  990.     }
  991.     getpkt = tproto->a;
  992.     sendpkt = tproto->b;
  993.     openpk = tproto->c;
  994.     closepk = tproto->d;
  995.     filepkt = tproto->e;
  996.     eofpkt = tproto->f;
  997.     getmsg = tproto->g;
  998.     sendmsg = tproto->h;
  999.     sendresp = tproto->i;
  1000. }
  1001.  
  1002.  
  1003.  
  1004. /**/
  1005. int prefix(sh,lg)
  1006. char *sh,*lg;
  1007. {
  1008.     return( strncmp(sh,lg,strlen(sh)) == SAME);
  1009. }
  1010.  
  1011. int notin(sh,lg)
  1012. char *sh,*lg;
  1013. {
  1014.     while (*lg) {
  1015.         if (prefix(sh,lg++))
  1016.             return( FALSE );
  1017.     }
  1018.     return( TRUE );
  1019. }
  1020.  
  1021. #define MAXR 300
  1022. int
  1023. expectstr( str, timeout )
  1024. char *str;
  1025. long int timeout;
  1026. {
  1027.     static char rdvec[MAXR];
  1028.     char *rp = rdvec;
  1029.     char expectstr[MAXR];
  1030.     int kr;
  1031.     int totlen, strip, iter, i, special;
  1032.     int totReceived;
  1033.     char nextch;
  1034.     int nbreaks, breakno;
  1035.     char *breaks[10], *breakout;
  1036.     
  1037.     nbreaks = 0;
  1038.     totReceived = 0;
  1039.  
  1040.     printmsg( 1, "wanted %s", str );
  1041.  
  1042.     if ( strcmp(str, "\"\"") == SAME ) {
  1043.         return( TRUE );
  1044.     }
  1045.     i = 0;
  1046.     totlen = 0;
  1047.     special = 0;
  1048.     while (i < strlen(str)) {
  1049.         nextch = str[i++];
  1050.         if (special) {
  1051.             switch (nextch) {
  1052.             case 's':
  1053.                 expectstr[totlen++] = ' ';
  1054.                 break;
  1055.             case 'r':
  1056.                 expectstr[totlen++] = '\r';
  1057.                 break;
  1058.             case 'n':
  1059.                 expectstr[totlen++] = '\n';
  1060.                 break;
  1061.             case 't':
  1062.                 expectstr[totlen++] = '\t';
  1063.                 break;
  1064.             default:
  1065.                 expectstr[totlen++] = nextch;
  1066.                 break;
  1067.             }
  1068.             special = 0;
  1069.         } else if (nextch == '\\') {
  1070.             special = 1;
  1071.         } else {
  1072.             expectstr[totlen++] = nextch;
  1073.         }
  1074.     }
  1075.     expectstr[totlen] = '\0';
  1076.     if (breakout = strchr(expectstr, 'Ñ')) {
  1077.         do {
  1078.             *breakout++ = '\0';
  1079.             breaks[nbreaks++] = breakout;
  1080.             breakout = strchr(breakout, 'Ñ');
  1081.         } while (breakout);
  1082.     }
  1083.     *rp = 0;
  1084.     while ( notin( expectstr,rdvec ) ) {
  1085.         printmsg(9, "Got '%s', match on '%s''", rdvec, expectstr);
  1086.         for (breakno = nbreaks-1 ; breakno >= 0; breakno--) {
  1087.             if (!notin(breaks[breakno], rdvec)) {
  1088.                 printmsg(0, breaks[breakno]);
  1089.                 return( FALSE );
  1090.             }
  1091.         }
  1092. #ifdef MULTIFINDER
  1093.         if (Main_State != Call_Systems) {
  1094.             return ( FALSE );
  1095.         }
  1096. #endif
  1097.         /* fprintf(stderr, "---------->%s<------\n", rdvec);/**/
  1098.         kr = sread(&nextch, 1, timeout);
  1099.         if (kr <= 0) {
  1100.             return( FALSE );
  1101.         }
  1102.         if (debuglevel >= 7) {
  1103.             fputc(nextch & 0177, stdout);
  1104.         }
  1105.         totReceived++;
  1106.         if (totReceived > MAXR * 10) { /* "Enough, already!" gibberish blocker */
  1107.             printmsg(2, "He seems to be babbling...");
  1108.             return (FALSE);
  1109.         }
  1110.         if ((*rp = nextch & 0177) != '\0') {
  1111.             rp++;
  1112.         }
  1113.         if (rp >= rdvec + MAXR) { /* off end, need to toss old stuff */
  1114.             strip = MAXR - totlen - 2;
  1115.             iter = strip;
  1116.             while (iter < MAXR) {
  1117.                 rdvec[iter-strip] = rdvec[iter];
  1118.                 iter++;
  1119.             }
  1120.             rp -= strip;
  1121.         }
  1122.         *rp = '\0';
  1123.     }
  1124.     return( TRUE );
  1125. }
  1126.  
  1127. int
  1128. writestr(s)
  1129.     register char *s; {
  1130.     register char last;
  1131.     register char * m;
  1132.     char ctlchar;
  1133. #ifdef MULTIFINDER
  1134.     long Last_Ticks;
  1135. #endif
  1136.     int nocr, pace;
  1137.     last = '\0';
  1138.     nocr = pace = FALSE;
  1139.     while (*s) {
  1140.         if (last == '\\') {
  1141.             switch (*s) {
  1142.             case 'd':
  1143.             case 'D': /* delay */
  1144. #ifdef MULTIFINDER
  1145.                 Last_Ticks = Ticks;
  1146.                 while (Ticks-Last_Ticks < 120) 
  1147.                   if (Check_Events(30))
  1148.                     if (Main_State == Abort_Program)  {
  1149.                         SIOClose(TRUE);
  1150.                         exit(-1);
  1151.                     }
  1152. #else
  1153.                 delay(80000);
  1154. #endif
  1155.                break;
  1156.             case 'c':
  1157.             case 'C': /* end string don't output CR */
  1158.                nocr = TRUE;
  1159.                break;
  1160.             case 'r':
  1161.             case 'R': /* carriage return */
  1162.             case 'm':
  1163.             case 'M':
  1164.                   swrite( "\r", 1 );
  1165.                   if (pace) paceit();
  1166.                    break;
  1167.             case 'n':
  1168.             case 'N':
  1169.                   swrite( "\n", 1 );
  1170.                   if (pace) paceit();
  1171.                    break;
  1172.             case 'b':
  1173.             case 'B':
  1174.                   swrite( "\b", 1 );
  1175.                   if (pace) paceit();
  1176.                    break;
  1177.             case 't':
  1178.             case 'T':
  1179.                   swrite( "\t", 1 );
  1180.                   if (pace) paceit();
  1181.                    break;
  1182.             case 's':
  1183.             case 'S':
  1184.                   swrite( " ", 1 );
  1185.                   if (pace) paceit();
  1186.                    break;
  1187.             case 'z':
  1188.             case 'Z':
  1189.                 SIOSpeed( ++s );
  1190.                 while ( *s != '\0' && *s != '\\' )
  1191.                     s++;
  1192.                 if ( *s == '\\' )
  1193.                     s++;
  1194.                 break;
  1195. #ifdef Upgrade
  1196.             case 'p':
  1197.             case 'P':
  1198.                   if (pace = ! pace) paceit();
  1199.                 break;
  1200.             case '0':
  1201.             case '1':
  1202.             case '2':
  1203.             case '3':
  1204.             case '4':
  1205.             case '5':
  1206.             case '6':
  1207.             case '7':
  1208.             case '8':
  1209.             case '9':
  1210.                 for(systimeout = *s++ - '0' ; *s < '9' && *s >= '0' ; ) {
  1211.                     systimeout *= 10;
  1212.                     systimeout += *s++ - '0';
  1213.                 }
  1214.                 s--; /* incremented later - before next time round loop */
  1215.                 printmsg(3, "expect timeout set to %hd", systimeout);
  1216.                 break;
  1217. #endif Upgrade
  1218.             default:
  1219.                   swrite( s, 1 );
  1220.                   if (pace) paceit();
  1221.             }
  1222.             last = '\0';
  1223.         }
  1224.         else if (last == '^') {
  1225.             ctlchar = *s & 0x1f;
  1226.             swrite(&ctlchar, 1);
  1227.               if (pace) paceit();
  1228.             last = '\0';
  1229.         }    
  1230.         else if (*s != '\\' && *s != '^') {
  1231.               swrite( s, 1 );
  1232.               if (pace) paceit();
  1233.         }
  1234.         else {
  1235.             last = *s;
  1236.         }
  1237.         s++;
  1238.     }
  1239.     return( nocr );
  1240. }
  1241.  
  1242. /***
  1243.  *   void sendthem(str)   send line of login sequence
  1244.  *         char *str;
  1245.  *
  1246.  *   return codes:  none
  1247.  */
  1248.  
  1249. void sendstr(str)
  1250. char *str;
  1251. {
  1252.     int nw, ns;
  1253.     int nulls;
  1254.  
  1255.     printmsg( 2, "sending %s", str );
  1256.  
  1257. #ifdef BREAK
  1258.     if (prefix("BREAK", str)) {
  1259.         sscanf(&str[5], "%1d", &nulls);
  1260.         if (nulls <= 0 || nulls > 10)
  1261.             nulls = 3;
  1262.         /* send break */
  1263.         ssendbrk(nulls);
  1264.         return;
  1265.     }
  1266. #endif BREAK
  1267.  
  1268.     if ( strcmp(str, "EOT") == SAME ) {
  1269.         swrite(EOTMSG, strlen(EOTMSG));
  1270.         return;
  1271.     }
  1272.  
  1273.     if ( strcmp(str,"\"\"") == SAME )
  1274.         *str = '\0';
  1275.         /*fprintf(stderr,"'%s'\n",str);*/
  1276.  
  1277.     if ( strcmp(str,"") != SAME ) {
  1278.         if (!writestr(str)) {
  1279.             swrite ("\r", 1);
  1280.         }
  1281.     }
  1282.     else {
  1283.         swrite("\r", 1);
  1284.     }
  1285.     return;
  1286. }
  1287.  
  1288. int
  1289. sendexpect(s, e, timeout)
  1290.     char *s;
  1291.     char *e;
  1292.     long int timeout; {
  1293.  
  1294.     sendstr(s);
  1295.     
  1296. #ifdef Upgrade
  1297.     if(systimeout > 0)
  1298.         return(expectstr(e, systimeout));
  1299. #endif Upgrade
  1300.  
  1301.     return(expectstr(e, timeout));
  1302. }
  1303.  
  1304. dial()
  1305. {
  1306.     int    flg, kk, jj, ll, firstflg;
  1307.     char    buf[4], *prsend;
  1308.  
  1309.     char *exp;
  1310.     char *alternate;
  1311.     int    ok;
  1312.     int i;
  1313.     int dialpause;
  1314.     static char HayesInitString[] = "\\p\\dAAATX4Q0V1E0";
  1315.     long minutes_to_sleep;
  1316.  
  1317. #ifdef Upgrade
  1318.     char number[128];
  1319.     char dialstring[256];
  1320.  
  1321.     if ( strcmp( flds[FLD_TYPE], "VADIC" ) == SAME ) {
  1322.         if (rmtname[0] != 0) printmsg( 0, "Dialing host %s", rmtname );
  1323.         if (openline(device, speed ))
  1324.             return( FALSE );
  1325.     
  1326.         SIOAllowInterrupts(TRUE);
  1327.         printmsg( 2, "vadic: autobauding" );
  1328.         if ( sendexpect( "\005\\d", "*", 2 ) != TRUE &&
  1329.          sendexpect( "\005\\d", "*", 2 ) != TRUE ) {
  1330.             printmsg( 0, "vadic: no response to autobaud" );
  1331.             return( FALSE);
  1332.         }
  1333.         printmsg( 1, "vadic: got modem response" );
  1334.     
  1335.         if (sendexpect ("dial", "NUMBER?", 5) != TRUE ) {
  1336.             printmsg( 2, "vadic: dial command rejected" );
  1337.             sendstr("I\dIDLE\\r");
  1338.             return( FALSE);
  1339.         }
  1340.         
  1341.         strcpy(number, "\\d");
  1342.         strcat(number, phone);
  1343.         strcat(number, "\\r\\d");
  1344.         if ( sendexpect(number, "DIALING...ÑNO DIAL TONE", 5) != TRUE ) {
  1345.             printmsg( 0, "vadic: could not initiate dial" );
  1346.             sendstr("I\dIDLE\\r");
  1347.             return(FALSE);
  1348.         }
  1349.     
  1350.         if ( sendexpect( "\\d\\c", "ON LINEÑBUSYÑFAILED CALL", 40 ) == TRUE ) {
  1351.             printmsg( 3, "vadic: ON LINE" );
  1352.             return( TRUE );
  1353.         }
  1354.         else {
  1355.             sendstr("I\dIDLE\\r");
  1356.             return( FALSE );
  1357.         }
  1358.     }
  1359.  
  1360. #endif
  1361.  
  1362.     if ( strncmp( flds[FLD_TYPE], "HAYES", 5 ) != SAME ) {
  1363.         printmsg( 2, "dial: unsupported dialer %s", flds[FLD_TYPE] );
  1364.         return( FALSE );
  1365.     }
  1366.  
  1367.     if (rmtname[0] != 0) printmsg( 0, "Dialing host %s", rmtname );
  1368.     if (openline(device, speed ))
  1369.         return( FALSE );
  1370.  
  1371.     SIOAllowInterrupts(TRUE);
  1372.     
  1373.     strcpy(dialstring, HayesInitString);
  1374.     if (flds[FLD_TYPE][5] != '\0' && flds[FLD_TYPE][6] != '\0') { /* for HAYES+ and HAYES! */
  1375.         strcat(dialstring, flds[FLD_TYPE]+6);
  1376.     }
  1377.     printmsg( 2, "hayes: autobauding" );
  1378.     if ( sendexpect( dialstring, "OK", 2 ) != TRUE &&
  1379.          sendexpect( dialstring, "OK", 2 ) != TRUE) {
  1380.         sendexpect( "\\d\\p+++", "OK", 2 );
  1381.         if ( sendexpect( "\\pAAATZ", "OK", 2 ) != TRUE ||
  1382.              sendexpect( dialstring, "OK", 2 ) != TRUE) {
  1383.             printmsg(0, "hayes: could not get modem's attention");
  1384.             return( FALSE);
  1385.         }
  1386.     }
  1387.     printmsg( 1, "hayes: got modem response" );
  1388. /*    zzz(1); */
  1389.     
  1390.     strcpy(dialstring, "\\pAAAT");    
  1391.     
  1392.     if (strcmp(phone, "-") == SAME) {
  1393.         strcat(dialstring, "S0=1");
  1394.         sscanf(sleeptime, "%ld", &minutes_to_sleep);
  1395.         if (minutes_to_sleep < 1) minutes_to_sleep = 1;
  1396.         dialpause = minutes_to_sleep * 60;
  1397.     } else {
  1398.         if (isdigit(*phone)) {
  1399.             strcat(dialstring, "DT");
  1400.         }
  1401.         strcat(dialstring, phone);
  1402.         dialpause = 120;
  1403.     }
  1404.  
  1405.     if ( sendexpect( dialstring, "CONNECT ÑBUSYÑNO CARRIERÑNO DIAL TONE", dialpause ) == TRUE ) {
  1406.         printmsg( 3, "hayes: got CONNECT" );
  1407.  
  1408.         if ( flds[FLD_TYPE][5] != '!' && sread( buf, 4, 4 ) == 4 ) {
  1409.             printmsg( 3, "hayes: speed select %s", buf );
  1410.             /* set speed appropriately */
  1411.             SIOSpeed( buf );
  1412.         }
  1413.         return( TRUE );
  1414.     }
  1415.     else {
  1416.         SIOAllowInterrupts(FALSE);
  1417.         sendexpect("\r\\d\\pAAATZ", "OK", 4);
  1418.         return( FALSE );
  1419.     }
  1420.  
  1421. }
  1422.  
  1423.  
  1424. /*
  1425. **
  1426. **callup
  1427. ** script processor - nothing fancy!
  1428. */
  1429. callup()
  1430. {
  1431.     int    flg, kk, jj, ll, firstflg;
  1432.     char    *prsend;
  1433.  
  1434.     char *exp;
  1435.     char *alternate;
  1436.     int    ok;
  1437.     int i;
  1438.  
  1439.     if (rmtname[0] != 0) printmsg( 0, "Calling %s (%s)", rmtname, callcause );
  1440.  
  1441.     if ( strcmp( flds[FLD_TYPE], "DIR" ) != SAME ) {
  1442.         if ( dial() == FALSE ) {
  1443.             if (rmtname[0] != 0) printmsg(0, "Dial failed");
  1444.             return( 'X' );
  1445.         }
  1446.     }
  1447.     else if (openline(device, speed))
  1448.         return( 'G' );
  1449.  
  1450.     SIOAllowInterrupts(TRUE);
  1451.  
  1452.     for (i = FLD_EXPECT; i < kflds; i+=2) {
  1453.  
  1454.         exp = flds[i];
  1455.         printmsg( 2, "callup: expect %d of %d  \"%s\"", i, kflds, exp );
  1456.  
  1457.         ok = FALSE;
  1458.         while (ok != TRUE) {
  1459.  
  1460.             alternate = index( exp, '-' );
  1461.             if (alternate != (char *)NULL)
  1462.                 *alternate++ = '\0';
  1463. #ifdef Upgrade
  1464.             ok = expectstr(exp, (systimeout > 0 ? systimeout : (10+2*strlen(exp))));
  1465. #else Upgrade
  1466.             ok = expectstr( exp, 10+2*strlen(exp) );
  1467. #endif Upgrade
  1468.  
  1469.             printmsg( 2, "got %s", ok != TRUE ? "?" : "that" );
  1470.  
  1471.             if ( ok == TRUE ) {
  1472.                 printmsg( 2, "got that" );
  1473.                 break;
  1474.             }
  1475.  
  1476.             if ( alternate == (char *)NULL ) {
  1477.                 printmsg( 0, "Login failed" );
  1478.                 return( 'X' );
  1479.             }
  1480.  
  1481.             exp = index( alternate, '-' );
  1482.             if ( exp != (char *)NULL )
  1483.                 *exp++ = '\0';
  1484.  
  1485.             printmsg( 1, "send alternate" );
  1486.  
  1487.             sendstr( alternate );
  1488.         }
  1489.  
  1490.     printmsg( 2, "callup: send %d of %d  \"%s\"", i+1, kflds, flds[i+1] );
  1491. #ifdef MULTIFINDER
  1492.     {
  1493.       long Last_Ticks;
  1494.       int status = 0;
  1495.     
  1496.       Last_Ticks = Ticks;
  1497.       while (Ticks-Last_Ticks < 60)
  1498.         if (Check_Events(15)) {
  1499.           printmsg( 0, "Call cancelled by operator" );
  1500.           SIOClose(TRUE);
  1501.           return( 'X' );
  1502.         }
  1503.     }
  1504. #else
  1505.     zzz(1);
  1506. #endif
  1507.     sendstr(flds[i+1]);
  1508.     }
  1509.     printmsg( 0, "Connected");
  1510.     return('P');
  1511.  
  1512. }
  1513.  
  1514. /**/
  1515. /*
  1516. **
  1517. **      slowrite
  1518. ** comunication slow write. needed for auto-baud modems
  1519. */
  1520. /*slowrite(st)
  1521. register char    *st;
  1522. {
  1523.     int    len, j;
  1524.     char    c;
  1525.     len = strlen(st);
  1526.     printmsg( 2, "sent %s", st );
  1527.     for (j = 0; j < len; j++) {
  1528.         swrite(&st[j], 1);
  1529.         ddelay(80000);
  1530.     }
  1531. }
  1532. */
  1533.  
  1534. /**/
  1535. /*
  1536. **
  1537. **scandir
  1538. **
  1539. */
  1540.  
  1541. #include "ndir.h"
  1542.  
  1543.  
  1544. /*    scandir
  1545.  
  1546.     scan work dir for C. files matching current remote host (rmtname)
  1547.  
  1548.     return
  1549.  
  1550.         A    - abort
  1551.         Y    - can't open file
  1552.         S    - ok
  1553.         Q    - no files
  1554.  
  1555. */
  1556. scandir()
  1557. {
  1558.     int    fn, len, i;
  1559.     char    cname[40], tmp[132];
  1560.  
  1561.     DIR *dirp;
  1562.     struct direct *dp;
  1563.  
  1564.     if ((dirp = opendir( spooldir )) == (DIR *)NULL ) {
  1565.         fprintf( stderr, "couldn't open dir %s\n", spooldir );
  1566.         return( 'A' );
  1567.     }
  1568. #ifdef Upgrade
  1569.     sprintf(cname, "%s%s", CALLFILE, rmtname);
  1570. #else Upgrade
  1571.     sprintf(cname, CALLFILE, rmtname);
  1572. #endif Upgrade
  1573.     len = strlen(cname);
  1574.     if (len > 9) len = 9;
  1575.     while ((dp = readdir(dirp)) != (struct direct *)NULL) {
  1576.         printmsg( 4, "scandir: %s", dp->d_name );
  1577.         if ( strncmp( cname, dp->d_name, len ) == SAME ) {
  1578.             printmsg( 4, "scandir: match!!" );
  1579.             strcpy(cfile, dp->d_name);
  1580. #ifdef Upgrade
  1581.             /* don't forget to close the last cfile */
  1582.             if (fw != (FILE *)NULL) {
  1583.                 fclose(fw);
  1584.                 fw = (FILE *)NULL;
  1585.             }
  1586. #endif Upgrade
  1587.             if ((fw = FOPEN( cfile, "r", 't' )) == (FILE *)NULL ) {
  1588.                 closedir( dirp );
  1589.                 return('Y');
  1590.             }
  1591.             closedir( dirp );
  1592.             strcpy(callcause, "work pending");
  1593.             return('S');
  1594.         }
  1595.     }
  1596.     closedir( dirp );
  1597.     return('Q');
  1598.  
  1599. }
  1600.  
  1601.  
  1602. /**/
  1603. /*
  1604. **
  1605. **dscandir
  1606. ** scan the directory
  1607. */
  1608.  
  1609. dscandir()
  1610. {
  1611.     int    fn, len, i;
  1612.     char    cname[40], tmp[132];
  1613.  
  1614.     DIR *dirp;
  1615.     struct direct *dp;
  1616.  
  1617.  
  1618.     if ((dirp = opendir( spooldir )) == (DIR *)NULL ) {
  1619.         printmsg( 0, "** couldn't open dir %s\n", spooldir );
  1620.         return(-1);
  1621.     }
  1622. #ifdef Upgrade
  1623.  
  1624.     /* we probably want ALL X. files to be processed every chance we get
  1625.      * in order to pick up any left behind by crashes before they could
  1626.      * be dealt with. In any case the #else Upgrade code was incorrect
  1627.      * and this fixes that A.S.
  1628.      */
  1629. # ifndef TOORESTRICTIVE
  1630.     strcpy(cname, XQTFILE);
  1631. # else TOORESTRICTIVE
  1632.     sprintf(cname, "%s%s", XQTFILE, rmtname); /* may be too restrictive */
  1633. # endif TOORESTRICTIVE
  1634.  
  1635. #else Upgrade
  1636.     sprintf(cname, XQTFILE, rmtname); /* sprintf(cname,"c%.4s",rmtname); */
  1637. #endif Upgrade
  1638.     len = strlen(cname);
  1639.     while ((dp = readdir(dirp)) != (struct direct *)NULL) {
  1640.         printmsg( 4, "dscandir: file = %s cname = %s", dp->d_name, cname );
  1641.         if ( strncmp( cname, dp->d_name, len ) == SAME ) {
  1642.             printmsg( 4, "dscandir: match!!" );
  1643.             strcpy(cfile, dp->d_name);
  1644.             closedir( dirp );
  1645.             return( -1 );
  1646.         }
  1647.     }
  1648.     closedir( dirp );
  1649.     return( 0 );
  1650. }
  1651.